package com.lch.netty.netty.tomcat;

import com.lch.netty.bio.tomcat.http.Servlet;
import com.lch.netty.netty.tomcat.http.NServlet;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.util.concurrent.FutureListener;

/**
 * @author: liuchenhui
 * @create: 2019-10-14 12:59
 **/
@SuppressWarnings("all")
public class NTomcat {

    /**
     * 1、解析xml(properties)文件，获取url与类实例的map 2、开启监听8080端口的ServerSocket 3、接收到浏览器的请求，并创建request,response
     * 4、通过request中的url找到服务 5、处理逻辑，通过response返回数据
     */

    private int port = 8080;
    private Properties properties = new Properties();
    private Map<String, NServlet> xmlMap = new HashMap<>();

    public NTomcat(int port) {
        this.port = port;
    }

    public NTomcat init() throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        String path = this.getClass().getResource("/").getPath();
        FileInputStream fileInputStream = new FileInputStream(path + "tomcat.properties");
        properties.load(fileInputStream);

        Set<Object> objects = properties.keySet();
        for (Object k : objects) {
            String kStr = (String) k;
            if (!kStr.endsWith("url")) {
                continue;
            }
            String serverName = kStr.replace(".url", "");
            String url = properties.getProperty(kStr);
            String serverClass = properties.getProperty(serverName + ".servlet");
            xmlMap.put(url, (NServlet) Class.forName(serverClass).newInstance());
        }
        return this;
    }

    public void start() {
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {

            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            pipeline.addLast(new HttpResponseEncoder())
                                    .addLast(new HttpRequestDecoder())
                                    .addLast(new ServletHandler(xmlMap));
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            ChannelFuture sync = serverBootstrap.bind(port).sync();
            System.out.println("Netty Tomcat已启动，监听端口" + port);
            sync.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
        NTomcat tomcat = new NTomcat(8088).init();

        tomcat.start();
    }

}
